/*
    组件之间的通信 
    
    1. 父子 组件 
    <A>
        <B></B>
    </A>
    2. 兄弟组件 
    <A></A>
    <B></B>

    props 传递数据
    state 修改数据 

    子组件如何修改父组件
    1. 反向 props  父组件把修改自身变量state的方法 通过 props 传递给子组件 子组件触发 

    
    兄弟组件通信
    1. 中间人模式  子组件A 去修改父组件  父组件再去修改 组件B 
    a. 子改父   反向props  + props
    b. 子改父   反向props  + ref 


    2. 事件机制  bus 事件总线  event (emit on once)
    emit 发送事件
    on 监听事件
    once 监听一次
    remove 移除事件


    架构
    flux  redux mobx  event 


    受控的Input 组件
    受控的组件  input 绑定动态的 value  value 受state 状态控制的  只有state改变 input才能改变
    非受控的组件  value 没有绑定状态 


*/

import React, { Component } from 'react';
import MyBtn from './MyBtn';
import EventEmitter from "events"  // 无需安装 Node自带

const bus = new EventEmitter() // emit on remove once
class MyState2 extends Component {
    state = {
        count: 2000,
        msg: "wh2201 - daydayup - 天天进步一点点",
        show: true
    }
    changeCound = (count) => {
        this.setState({
            count: this.state.count + count
        })
    }
    changeMsg = (msg) => {
        this.setState({ msg:msg })
    }
    changeShow = show => {
        this.setState({ show })
    }
    changeChildTwo=()=>{
        this.child2.setState({
            message:'wh2201 - 早起写代码，晚睡背面试题...'
        })
    }
    render() {
        const {
            count, msg, show
        } = this.state
        return (
            <div>
                <h2>React 组件通信（子改父）</h2>
                <h3>count - {count}</h3>
                <h3>msg - {msg}</h3>
                <div style={{ width: 220, height: 140, background: 'orange', borderRadius: 15, display: show ? 'flex' : 'none', justifyContent: 'center', alignItems: 'center' }}>
                    我是被父组件给点击切换的
                </div>
                <hr />
                <MyChild
                    changeCound={this.changeCound}
                    changeMsg={this.changeMsg}
                    show={show}
                    changeShow={this.changeShow}  //记住要展开，写在这里的
                    changeChildTwo={this.changeChildTwo}
                />
                <MyChildTwo
                count = {count}
                msg = {msg}
                show = {show}
                ref={el=>this.child2=el}
                />
            </div>
        );
    }
}



class MyChild extends Component {
    changeByBus=()=>{
        // emit 监听
        bus.emit("changeByBus","通过事件总线修改了Message")
    }
    changeTwoNum=()=>{
        bus.emit("changeTwoNum",200)
    }
    render() {
        // 解构  父亲 把修改自身的方法通过props传递给子组件
        const { changeCound, changeMsg, changeShow , show,changeChildTwo} = this.props
        return (
            <div>
                <h2>MyChild - MyChild - 1子组件</h2>
                {/* 带（）括号就要带箭头函数 */}
                <MyBtn text="修改父亲的count" onClick={() => changeCound(200)}></MyBtn>
                <p>
                    {/* this.inp.value 直接指向这个input框 ref */}
                    <input type="text" placeholder='修改父亲的msg' ref={el => this.inp = el} onChange={() => changeMsg(this.inp.value)} />
                </p>
                {/* 有参数的一定会带箭头函数 */}
                <MyBtn text="修改父亲的show" onClick={()=>changeShow(!show)}></MyBtn>
                <MyBtn text="修改兄弟组件2" onClick={changeChildTwo}></MyBtn>
                <MyBtn text="事件总线去修改兄弟组件2" onClick={this.changeByBus}></MyBtn>
                <MyBtn text="事件总线去修改兄弟组件2 == Num" onClick={this.changeTwoNum}></MyBtn>
            </div>
        );
    }
}



class MyChildTwo extends Component {
    state ={
        message:"2201 - 天道酬勤",
        num :8000
    }

    // mounted
    componentDidMount(){
        bus.on("changeByBus",msg=>{
            this.setState({
                message:msg
            })
        })
        bus.on("changeTwoNum",num=>{
            this.setState({
                num:this.state.num+num
            })
        })
    }
    render() {
        const {count,msg,show} = this.props;
        const {message,num} =this.state
        return (
            <div>
                <h2>MyChildTwo - MyChildTwo - 2子组件</h2>
                <h2>message == {message}</h2>
                <h1>num== {num}</h1>
                <h2> count -- {count}</h2>
                <h2>msg -- {msg}</h2>
                <h2>show -- {show?'晚上下雨':'晚上不下雨'}</h2>
            </div>
        );
    }
}



export default MyState2;
